#include "stdafx.h"
#include "utils/numberformatter.hpp"
#include "stdlib/bugcheck.hpp"
using namespace JHCPP::stdlib;
#include "stream/streambuf.hpp"
using namespace JHCPP::stream;

#include <iomanip>
#include <locale>
#include <cstdio>

#if defined(_MSC_VER) || defined(__MINGW32__ )
#define I64_FMT "I64"
#else
#define I64_FMT "ll"
#endif

namespace JHCPP
{
	namespace utils
	{
		std::string CNumberFormatter::format(int value)
		{
			std::string result;
			append(result, value);
			return result;
		}

		std::string CNumberFormatter::format(unsigned value)
		{
			std::string result;
			append(result, value);
			return result;
		}

		std::string CNumberFormatter::format(long value)
		{
			std::string result;
			append(result, value);
			return result;
		}

		std::string CNumberFormatter::format(unsigned long value)
		{
			std::string result;
			append(result, value);
			return result;
		}

		std::string CNumberFormatter::format(Int64 value)
		{
			std::string result;
			append(result, value);
			return result;
		}

		std::string CNumberFormatter::format(UInt64 value)
		{
			std::string result;
			append(result, value);
			return result;
		}

		std::string CNumberFormatter::format(float value)
		{
			std::string result;
			append(result, value);
			return result;
		}

		std::string CNumberFormatter::format(double value)
		{
			std::string result;
			append(result, value);
			return result;
		}

		std::string CNumberFormatter::format(const void* ptr)
		{
			std::string result;
			append(result, ptr);
			return result;
		}


		std::string CNumberFormatter::format(int value, int width)
		{
			std::string result;
			append(result, value, width);
			return result;
		}

		std::string CNumberFormatter::format(unsigned value, int width)
		{
			std::string result;
			append(result, value, width);
			return result;
		}

		std::string CNumberFormatter::format(long value, int width)
		{
			std::string result;
			append(result, value, width);
			return result;
		}

		std::string CNumberFormatter::format(unsigned long value, int width)
		{
			std::string result;
			append(result, value, width);
			return result;
		}

		std::string CNumberFormatter::format(Int64 value, int width)
		{
			std::string result;
			append(result, value, width);
			return result;
		}

		std::string CNumberFormatter::format(UInt64 value, int width)
		{
			std::string result;
			append(result, value, width);
			return result;
		}

		std::string CNumberFormatter::format(double value, int precision)
		{
			std::string result;
			append(result, value, precision);
			return result;
		}

		std::string CNumberFormatter::format(double value, int width, int precision)
		{
			std::string result;
			append(result, value, width, precision);
			return result;
		}


		std::string CNumberFormatter::format0(int value, int width)
		{
			std::string result;
			append0(result, value, width);
			return result;
		}

		std::string CNumberFormatter::format0(unsigned int value, int width)
		{
			std::string result;
			append0(result, value, width);
			return result;
		}

		std::string CNumberFormatter::format0(long value, int width)
		{
			std::string result;
			append0(result, value, width);
			return result;
		}

		std::string CNumberFormatter::format0(unsigned long value, int width)
		{
			std::string result;
			append0(result, value, width);
			return result;
		}

		std::string CNumberFormatter::format0(Int64 value, int width)
		{
			std::string result;
			append0(result, value, width);
			return result;
		}

		std::string CNumberFormatter::format0(UInt64 value, int width)
		{
			std::string result;
			append0(result, value, width);
			return result;
		}


		std::string CNumberFormatter::formatHex(int value)
		{
			std::string result;
			appendHex(result, value);
			return result;
		}

		std::string CNumberFormatter::formatHex(unsigned value)
		{
			std::string result;
			appendHex(result, value);
			return result;
		}

		std::string CNumberFormatter::formatHex(long value)
		{
			std::string result;
			appendHex(result, value);
			return result;
		}

		std::string CNumberFormatter::formatHex(unsigned long value)
		{
			std::string result;
			appendHex(result, value);
			return result;
		}

		std::string CNumberFormatter::formatHex(Int64 value)
		{
			std::string result;
			appendHex(result, value);
			return result;
		}

		std::string CNumberFormatter::formatHex(UInt64 value)
		{
			std::string result;
			appendHex(result, value);
			return result;
		}


		std::string CNumberFormatter::formatHex(int value, int width)
		{
			std::string result;
			appendHex(result, value, width);
			return result;
		}

		std::string CNumberFormatter::formatHex(unsigned value, int width)
		{
			std::string result;
			appendHex(result, value, width);
			return result;
		}

		std::string CNumberFormatter::formatHex(long value, int width)
		{
			std::string result;
			appendHex(result, value, width);
			return result;
		}

		std::string CNumberFormatter::formatHex(unsigned long value, int width)
		{
			std::string result;
			appendHex(result, value, width);
			return result;
		}

		std::string CNumberFormatter::formatHex(Int64 value, int width)
		{
			std::string result;
			appendHex(result, value, width);
			return result;
		}

		std::string CNumberFormatter::formatHex(UInt64 value, int width)
		{
			std::string result;
			appendHex(result, value, width);
			return result;
		}



		void CNumberFormatter::append(std::string& str, int value)
		{
			char buffer[64];
			std::sprintf(buffer, "%d", value);
			str.append(buffer);
		}

		void CNumberFormatter::append(std::string& str, unsigned value)
		{
			char buffer[64];
			std::sprintf(buffer, "%u", value);
			str.append(buffer);
		}

		void CNumberFormatter::append(std::string& str, long value)
		{
			char buffer[64];
			std::sprintf(buffer, "%ld", value);
			str.append(buffer);
		}

		void CNumberFormatter::append(std::string& str, unsigned long value)
		{
			char buffer[64];
			std::sprintf(buffer, "%lu", value);
			str.append(buffer);
		}

		void CNumberFormatter::append(std::string& str, Int64 value)
		{
			char buffer[64];
			std::sprintf(buffer, "%" I64_FMT "d", value);
			str.append(buffer);
		}

		void CNumberFormatter::append(std::string& str, UInt64 value)
		{
			char buffer[64];
			std::sprintf(buffer, "%" I64_FMT "u", value);
			str.append(buffer);
		}

		void CNumberFormatter::append(std::string& str, float value)
		{
			char buffer[64];
			CMemoryOutputStream ostr(buffer, sizeof(buffer));
			ostr.imbue(std::locale::classic());
			ostr << std::setprecision(8) << value;
			str.append(buffer, static_cast<std::string::size_type>(ostr.charsWritten()));
		}

		void CNumberFormatter::append(std::string& str, double value)
		{
			char buffer[64];
			CMemoryOutputStream ostr(buffer, sizeof(buffer));
			ostr.imbue(std::locale::classic());
			ostr << std::setprecision(16) << value;
			str.append(buffer, static_cast<std::string::size_type>(ostr.charsWritten()));
		}

		void CNumberFormatter::append(std::string& str, const void* ptr)
		{
			char buffer[24];
			std::sprintf(buffer, "%08lX", (UIntPtr) ptr);
			str.append(buffer);
		}


		void CNumberFormatter::append(std::string& str, int value, int width)
		{
			jh_assert (width > 0 && width < 64);

			char buffer[64];
			std::sprintf(buffer, "%*d", width, value);
			str.append(buffer);
		}

		void CNumberFormatter::append(std::string& str, unsigned value, int width)
		{
			jh_assert (width > 0 && width < 64);

			char buffer[64];
			std::sprintf(buffer, "%*u", width, value);
			str.append(buffer);
		}

		void CNumberFormatter::append(std::string& str, long value, int width)
		{
			jh_assert (width > 0 && width < 64);

			char buffer[64];
			std::sprintf(buffer, "%*ld", width, value);
			str.append(buffer);
		}

		void CNumberFormatter::append(std::string& str, unsigned long value, int width)
		{
			jh_assert (width > 0 && width < 64);

			char buffer[64];
			std::sprintf(buffer, "%*lu", width, value);
			str.append(buffer);
		}

		void CNumberFormatter::append(std::string& str, Int64 value, int width)
		{
			jh_assert (width > 0 && width < 64);

			char buffer[64];
			std::sprintf(buffer, "%*" I64_FMT "d", width, value);
			str.append(buffer);
		}

		void CNumberFormatter::append(std::string& str, UInt64 value, int width)
		{
			jh_assert (width > 0 && width < 64);

			char buffer[64];
			std::sprintf(buffer, "%*" I64_FMT "u", width, value);
			str.append(buffer);
		}

		void CNumberFormatter::append(std::string& str, double value, int precision)
		{
			jh_assert (precision >= 0 && precision < 32);

			char buffer[64];
			CMemoryOutputStream ostr(buffer, sizeof(buffer));
			ostr.imbue(std::locale::classic());
			ostr << std::fixed << std::showpoint << std::setprecision(precision) << value;
			str.append(buffer, static_cast<std::string::size_type>(ostr.charsWritten()));
		}

		void CNumberFormatter::append(std::string& str, double value, int width, int precision)
		{
			jh_assert (width > 0 && width < 64 && precision >= 0 && precision < width);

			char buffer[64];
			CMemoryOutputStream ostr(buffer, sizeof(buffer));
			ostr.imbue(std::locale::classic());
			ostr << std::fixed << std::showpoint << std::setw(width) << std::setprecision(precision) << value;
			str.append(buffer, static_cast<std::string::size_type>(ostr.charsWritten()));
		}
	

		void CNumberFormatter::append0(std::string& str, int value, int width)
		{
			jh_assert (width > 0 && width < 64);

			char buffer[64];
			std::sprintf(buffer, "%0*d", width, value);
			str.append(buffer);
		}

		void CNumberFormatter::append0(std::string& str, unsigned int value, int width)
		{
			jh_assert (width > 0 && width < 64);

			char buffer[64];
			std::sprintf(buffer, "%0*u", width, value);
			str.append(buffer);
		}

		void CNumberFormatter::append0(std::string& str, long value, int width)
		{
			jh_assert (width > 0 && width < 64);

			char buffer[64];
			std::sprintf(buffer, "%0*ld", width, value);
			str.append(buffer);
		}

		void CNumberFormatter::append0(std::string& str, unsigned long value, int width)
		{
			jh_assert (width > 0 && width < 64);

			char buffer[64];
			std::sprintf(buffer, "%0*lu", width, value);
			str.append(buffer);
		}

		void CNumberFormatter::append0(std::string& str, Int64 value, int width)
		{
			jh_assert (width > 0 && width < 64);

			char buffer[64];
			std::sprintf(buffer, "%0*" I64_FMT "d", width, value);
			str.append(buffer);
		}

		void CNumberFormatter::append0(std::string& str, UInt64 value, int width)
		{
			jh_assert (width > 0 && width < 64);

			char buffer[64];
			std::sprintf(buffer, "%0*" I64_FMT "u", width, value);
			str.append(buffer);
		}


		void CNumberFormatter::appendHex(std::string& str, int value)
		{
			char buffer[64];
			std::sprintf(buffer, "%X", value);
			str.append(buffer);
		}

		void CNumberFormatter::appendHex(std::string& str, unsigned value)
		{
			char buffer[64];
			std::sprintf(buffer, "%X", value);
			str.append(buffer);
		}

		void CNumberFormatter::appendHex(std::string& str, long value)
		{
			char buffer[64];
			std::sprintf(buffer, "%lX", value);
			str.append(buffer);
		}

		void CNumberFormatter::appendHex(std::string& str, unsigned long value)
		{
			char buffer[64];
			std::sprintf(buffer, "%lX", value);
			str.append(buffer);
		}

		void CNumberFormatter::appendHex(std::string& str, Int64 value)
		{
			char buffer[64];
			std::sprintf(buffer, "%" I64_FMT "X", value);
			str.append(buffer);
		}

		void CNumberFormatter::appendHex(std::string& str, UInt64 value)
		{
			char buffer[64];
			std::sprintf(buffer, "%" I64_FMT "X", value);
			str.append(buffer);
		}


		void CNumberFormatter::appendHex(std::string& str, int value, int width)
		{
			jh_assert (width > 0 && width < 64);

			char buffer[64];
			std::sprintf(buffer, "%0*X", width, value);
			str.append(buffer);
		}

		void CNumberFormatter::appendHex(std::string& str, unsigned value, int width)
		{
			jh_assert (width > 0 && width < 64);

			char buffer[64];
			std::sprintf(buffer, "%0*X", width, value);
			str.append(buffer);
		}

		void CNumberFormatter::appendHex(std::string& str, long value, int width)
		{
			jh_assert (width > 0 && width < 64);

			char buffer[64];
			std::sprintf(buffer, "%0*lX", width, value);
			str.append(buffer);
		}

		void CNumberFormatter::appendHex(std::string& str, unsigned long value, int width)
		{
			jh_assert (width > 0 && width < 64);

			char buffer[64];
			std::sprintf(buffer, "%0*lX", width, value);
			str.append(buffer);
		}

		void CNumberFormatter::appendHex(std::string& str, Int64 value, int width)
		{
			jh_assert (width > 0 && width < 64);

			char buffer[64];
			std::sprintf(buffer, "%0*" I64_FMT "X", width, value);
			str.append(buffer);
		}

		void CNumberFormatter::appendHex(std::string& str, UInt64 value, int width)
		{
			jh_assert (width > 0 && width < 64);

			char buffer[64];
			std::sprintf(buffer, "%0*" I64_FMT "X", width, value);
			str.append(buffer);
		}
	}//end of namespace utils
}//end of namespace JHCPP
